#include "rtsp_parser.h"
#include <cstring>

using namespace VLRTSP;


/**
 * @Author: CimZzz
 * @Date: 2022-01-11 17:43:22
 * 
 * 构造函数
 */
RTSPParser::RTSPParser(): crlfMatcher("\r\n") {
	this->method = NONE;
	this->methodStr = std::string("NONE");
	this->url = std::string("");
	this->ip = std::string("");
	this->trackId = -1;
	this->suffix = std::string("");
	this->port = 0;
	this->version = std::string("");
	this->cseq = std::string("");
	this->transport = TransportMode::Transport_NONE;
	this->rtpSendPoint = 0;
	this->rtcpSendPoint = 0;
	this->dispatcherId = 0;
}

/**
 * @Author: CimZzz
 * @Date: 2022-01-11 18:04:44
 * 
 * 析构函数
 */
RTSPParser::~RTSPParser() {

}



/**
 * @Author: CimZzz
 * @Date: 2022-01-11 18:05:18
 * 
 * 解析 RTSP 请求消息头
 * @param buffer 字节缓冲区
 * @return 如果解析成功返回 true
 */
bool RTSPParser::parseHeader(Buffer* buffer) {
	uint8_t* bufferPtr = buffer->getBuffer();
	uint32_t bufferLength = buffer->getBufferLength();
	uint32_t lineStartIndex = 0;
	bool hasHeader = false;
	int64_t lineEndIndex = 0;
	if(bufferPtr[0] == '$') {
		this->method = RTCP;
		this->methodStr = std::string("RTCP");
		return true;
	}

	for(; ; lineStartIndex = lineEndIndex + 2) {
		lineEndIndex = this->crlfMatcher.matchBefore(bufferPtr + lineStartIndex, bufferLength - lineStartIndex);
		if(lineEndIndex == -1) {
			goto PARSER_ERROR;
		}
		lineEndIndex += lineStartIndex;
		if(lineEndIndex - lineStartIndex == 0) {
			break;
		}
		std::string lineStr(bufferPtr + lineStartIndex, bufferPtr + lineEndIndex);
		if(!hasHeader) {
			// 解析首行
			// 方法 URI RTSP版本 CR LF
			char method[32] = {0};
			char url[400] = {0};
			char version[32] = {0};
			if(sscanf(lineStr.c_str(), "%s %s %s", method, url, version) != 3) {
				goto PARSER_ERROR;
			}

			this->url = std::string(url);

			// 校验 Method 方法
			std::string methodStr(method);
			if(methodStr == "OPTIONS") {
				this->method = OPTIONS;
			}
			else if(methodStr == "DESCRIBE") {
				this->method = DESCRIBE;
			}
			else if(methodStr == "SETUP") {
				this->method = SETUP;
			}
			else if(methodStr == "PLAY") {
				this->method = PLAY;
			}
			else if(methodStr == "TEARDOWN") {
				this->method = TEARDOWN;
			}
			else if(methodStr == "GET_PARAMETER") {
				this->method = GET_PARAMETER;
			}
			else {
				goto PARSER_ERROR;
			}

			this->methodStr = std::move(methodStr);

			// 校验 Url
			if(strncmp(url, "rtsp://", 7) != 0) {
				// Url 不合法
				goto PARSER_ERROR;
			}
			
			uint32_t port = 0;
			char ip[64] = {0};
			char suffix[64] = {0};

			char* matchUrl = url + 7;
			if(sscanf(url+7, "%[^:]:%hu/%s", ip, &port, suffix) == 3) {

			}
			else if(sscanf(url+7, "%[^/]/%s", ip, suffix) == 2) {
				port = 554;
			}
			else {
				goto PARSER_ERROR;
			}

			this->ip = std::string(ip);
			std::string suffixStr = std::string(suffix);
			uint32_t splitIdx = suffixStr.find('/');
			if(splitIdx != -1) {
				// 存在分割线
				this->suffix = suffixStr.substr(0, splitIdx);
				int32_t trackId = -1;
				if(sscanf(suffixStr.c_str() + splitIdx + 1, "trackID=%u", &trackId) == 1) {
					this->trackId = trackId;
				} else if(sscanf(suffixStr.c_str() + splitIdx + 1, "track%u", &trackId) == 1) {
					this->trackId = trackId;
				}
			} else {
				this->suffix = suffixStr;
			}
			this->port = port;
			this->version = std::string(version);

			hasHeader = true;
		}

		// 解析 RTSP 请求头
		int splitIdx = lineStr.find(':');
		if(splitIdx == -1) {
			continue;
		}
		std::string key = lineStr.substr(0, splitIdx);
		std::string value = lineStr.substr(splitIdx + 1);

		if(key.empty() || value.empty()) {
			continue;
		}

		key.erase(0, key.find_first_not_of(' '));
		key.erase(key.find_last_not_of(' ') + 1);
		value.erase(0, value.find_first_not_of(' '));
		value.erase(value.find_last_not_of(' ') + 1);
		if(key.empty() || value.empty()) {
			continue;
		}

		if(key == "CSeq") {
			this->cseq = std::move(value);
		} 
		else if (key == "Transport") {
			char transport[10] = {0};
			uint16_t rtpSendPoint, rtcpSendPoint;
			const char* valueStr = value.c_str();
			if(sscanf(valueStr, "%[^;]s;%*", transport) == 1) {
				std::string transportStr(transport);
				if(transportStr == "RTP/AVP") {
					// UDP 方式
					if(value.find("unicast") != std::string::npos) {
						// 单播
						this->transport = Transport_UDP;
						if (sscanf(valueStr, "%*[^;];%*[^;];%*[^=]=%hu-%hu", &this->rtpSendPoint, &this->rtcpSendPoint) != 2) {
							goto PARSER_ERROR;
						}
					}
					else if(value.find("multicast") != std::string::npos) {
						this->transport = Transport_MULTICAST;
					}
					else {
						goto PARSER_ERROR;
					}
				}
				else if(transportStr == "RTP/AVP/TCP"){
					// TCP 方式
					this->transport = Transport_TCP;
					if (sscanf(valueStr, "%*[^;];%*[^;];%*[^=]=%hu-%hu", &this->rtpSendPoint, &this->rtcpSendPoint) != 2) {
						goto PARSER_ERROR;
					}
				} else {
					this->transport = Transport_NONE;
				}
			}
		} 
		else if (key == "Session") {
			uint32_t dispatcherId = 0;
			if(sscanf(value.c_str(), "%u", &dispatcherId) == 1) {
				this->dispatcherId = dispatcherId;
			}
		}
		else {
			this->headerParamsMap[key] = value;
		}

	}

	if(!hasHeader) {
		goto PARSER_ERROR;
	}

	if(this->cseq == "") {
		goto PARSER_ERROR;
	}

	return true;

	PARSER_ERROR:
	this->reset();
	return false;
}

/**
 * @Author: CimZzz
 * @Date: 2022-01-11 18:14:06
 * 
 * 重置解析器
 */
void RTSPParser::reset() {
	this->method = NONE;
	this->methodStr = std::string("NONE");
	this->url = std::string("");
	this->ip = std::string("");
	this->trackId = -1;
	this->suffix = std::string("");
	this->port = 0;
	this->version = std::string("");
	this->cseq = std::string("");
	this->transport = TransportMode::Transport_NONE;
	this->rtpSendPoint = 0;
	this->rtcpSendPoint = 0;
	this->dispatcherId = 0;
	this->headerParamsMap.clear();
}


/**
 * @Author: CimZzz
 * @Date: 2022-01-12 16:25:11
 * 
 * 获取 RTSP 方法
 * @return RTSP 方法
 */
RTSPParser::RTSPMethod RTSPParser::getMethod() {
	return this->method;
}


/**
 * @Author: CimZzz
 * @Date: 2022-01-13 11:11:41
 * 
 * 获取 RTSP 方法名字符串
 * @return RTSP 方法名字符串
 */
std::string RTSPParser::getMethodStr() {
	return this->methodStr;
}

/**
 * @Author: CimZzz
 * @Date: 2022-01-12 16:25:11
 * 
 * 获取访问 IP
 * @return 访问 IP
 */
std::string RTSPParser::getIp() {
	return this->ip;
}

/**
 * @Author: CimZzz
 * @Date: 2022-01-12 16:26:27
 * 
 * 获取访问端口
 * @return 访问端口
 */
uint32_t RTSPParser::getPort() {
	return this->port;
}

/**
 * @Author: CimZzz
 * @Date: 2022-01-12 16:27:08
 * 
 * 获取地址路径前缀
 * @return 地址路径前缀
 */
std::string RTSPParser::getSuffix() {
	return this->suffix;
}



/**
 * @Author: CimZzz
 * @Date: 2022-01-13 18:00:54
 * 
 * 获取传输模式
 * @return 传输模式
 */
TransportMode RTSPParser::getTransportMode() {
	return this->transport;
}


/**
 * @Author: CimZzz
 * @Date: 2022-01-14 11:09:02
 * 
 * 获取轨道 Id
 * @return 轨道 Id
 */
uint32_t RTSPParser::getTrackId() {
	return this->trackId;
}

/**
 * @Author: CimZzz
 * @Date: 2022-01-13 18:01:13
 * 
 * 获取 RTP 端口 / Channel
 * @return RTP 端口 / Channel
 */
uint16_t RTSPParser::getRTPSendPoint() {
	return this->rtpSendPoint;
}

/**
 * @Author: CimZzz
 * @Date: 2022-01-13 18:01:34
 * 
 * 获取 RTCP 端口 / Channel
 * @return RTCP 端口 / Channel
 */
uint16_t RTSPParser::getRTCPSendPoint() {
	return this->rtcpSendPoint;
}

/**
 * @Author: CimZzz
 * @Date: 2022-01-14 17:34:35
 * 
 * 获取媒体分发器 Id
 * @return 媒体分发器 Id
 */
uint32_t RTSPParser::getDispatcherId() {
	return this->dispatcherId;
}

/**
 * +======================================================================================================================+
 * @Author: CimZzz
 * @Date: 2022-01-12 17:02:16
 * 
 * 代码分割块，以下内容涉及: 
 * 
 * 构建 RTSP 响应方法
 * 
 */



/**
 * @Author: CimZzz
 * @Date: 2022-01-13 17:47:17
 * 
 * 构建未找到资源的响应
 * @param buffer 字节缓冲区
 */
void RTSPParser::buildNotFoundResponse(Buffer* buffer) {
	buffer->appendPrint (
		"RTSP/1.0 404 Stream Not Found\r\n"
		"CSeq: %s\r\n"
		"\r\n",
		this->cseq.c_str()
	);
}

/**
 * @Author: CimZzz
 * @Date: 2022-01-13 17:48:00
 * 
 * 构建服务器异常的响应
 * @param buffer 字节缓冲区
 */
void RTSPParser::buildServerErrorResponse(Buffer* buffer) {
	buffer->appendPrint (
		"RTSP/1.0 500 Internal Server Error\r\n"
		"CSeq: %s\r\n"
		"\r\n",
		this->cseq.c_str()
	);
}

/**
 * @Author: CimZzz
 * @Date: 2022-01-13 17:48:46
 * 
 * 构建不支持传输方式的响应
 * @param buffer 字节缓冲区
 */
void RTSPParser::buildUnsupportedTransportResponse(Buffer* buffer) {
	buffer->appendPrint (
		"RTSP/1.0 461 Unsupported transport\r\n"
		"CSeq: %s\r\n"
		"\r\n",
		this->cseq.c_str()
	);
}

/**
 * @Author: CimZzz
 * @Date: 2022-01-12 17:02:44
 * 
 * 构建 Options 方法响应报文
 * @param buffer 字节缓冲区
 */
void RTSPParser::buildOptionsResponse(Buffer* buffer) {
	buffer->appendPrint(
		"RTSP/1.0 200 OK\r\n"
		"Server: VL_RTSPServer_1.0\r\n"
		"Content-Length: 0\r\n"
		"CSeq: %s\r\n"
		"Public: OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY\r\n"
		"\r\n",
		this->cseq.c_str()
	);
}


/**
 * @Author: CimZzz
 * @Date: 2022-01-13 17:21:02
 * 
 * 构建 Describe 方法响应报文
 * @param buffer 字节缓冲区
 * @param sdpBuffer SDP 描述文件缓冲区
 */
void RTSPParser::buildDescribeResponse(Buffer* buffer, Buffer* sdpBuffer) {
	buffer->appendPrint(
		"RTSP/1.0 200 OK\r\n"
		"CSeq: %s\r\n"
		"Content-Length: %u\r\n"
		"Content-Type: application/sdp\r\n"
		"\r\n",
		this->cseq.c_str(),
		sdpBuffer->getBufferLength()
	);
	buffer->appendBuffer(sdpBuffer);
}



/**
 * @Author: CimZzz
 * @Date: 2022-01-14 17:03:36
 * 
 * 构建 SETUP 方法响应报文
 * @param buffer 字节缓冲区
 * @param serverRTPPort 服务端 RTP 端口
 * @param serverRTCPPort 服务端 RTCP 端口
 * @param dispatchId 媒体数据分发器 Id
 * 
 * @note 使用 UDP 传输方式
 */
void RTSPParser::buildSetupByUdpResponse(Buffer* buffer, uint16_t serverRTPPort, uint16_t serverRTCPPort, uint32_t dispatchId) {
	buffer->appendPrint(
		"RTSP/1.0 200 OK\r\n"
		"CSeq: %s\r\n"
		"Transport: RTP/AVP;unicast;client_port=%hu-%hu;server_port=%hu-%hu\r\n"
		"Session: %u\r\n"
		"\r\n",
		this->cseq.c_str(),
		this->rtpSendPoint,
		this->rtcpSendPoint,
		serverRTPPort,
		serverRTCPPort,
		dispatchId
	);
}


/**
 * @Author: CimZzz
 * @Date: 2022-01-17 00:23:33
 * 
 * 构建 SETUP 方法响应报文
 * @param buffer 字节缓冲区
 * @param dispatchId 媒体数据分发器 Id
 * 
 * @note 使用 TCP 传输方式
 */
void RTSPParser::buildSetupByTcpResponse(Buffer* buffer, uint32_t dispatchId) {
	buffer->appendPrint(
		"RTSP/1.0 200 OK\r\n"
		"CSeq: %s\r\n"
		"Transport: RTP/AVP/TCP;unicast;interleaved=%d-%d\r\n"
		"Session: %u\r\n"
		"\r\n",
		this->cseq.c_str(),
		this->rtpSendPoint,
		this->rtcpSendPoint,
		dispatchId
	);
}

/**
 * @Author: CimZzz
 * @Date: 2022-01-14 17:03:36
 * 
 * 构建 PLAY 方法响应报文
 * @param buffer 字节缓冲区
 */
void RTSPParser::buildPlayResponse(Buffer* buffer) {
	buffer->appendPrint(
		"RTSP/1.0 200 OK\r\n"
		"CSeq: %s\r\n"
		"Range: npt=0.000-\r\n"
		"Session: %u; timeout=60\r\n",
		"\r\n",
		this->cseq.c_str(),
		this->dispatcherId
	);
}



/**
 * @Author: CimZzz
 * @Date: 2022-01-14 18:48:17
 * 
 * 构建 TEARDOWN 方法响应报文
 * @param buffer 字节缓冲区
 */
void RTSPParser::buildTeardownResponse(Buffer* buffer) {
	buffer->appendPrint(
		"RTSP/1.0 200 OK\r\n"
		"CSeq: %s\r\n"
		"Session: %u\r\n"
		"\r\n",
		this->cseq.c_str(),
		this->dispatcherId
	);
}